package nachos.threads;

/**
 *安排对某些特定受某些常量限制的资源的访问.一个线程队列可以在多个线程中共享这种受限的访问.
 * 在nachos中,受限访问包括但不仅限于:
 * <p>
 * <ol>
 * <li>thread使用CPU处理器(processor)的权利.同一时间只有一个线程可以使用处理器.
 * <li>thread获得特定锁的权利.一把锁在同一时间只能被一个线程所持有.
 * <li>当semaphore为0,thread从Semaphore.P()(wait操作)返回的权利.
 * 	当另一个线程调用Semaphore.V()(signal操作),只有一个等待Semaphore.P()的操作可以被唤醒
 * <li>因为条件变量而睡眠的简称被唤醒的权利.当另一个线程调用Condition.wake()操作时,只有一个因条件变量睡眠的线程可以被唤醒
 * <li>线程从KThread.join()返回的权利.直到目标线程完成时,线程才被允许从join方法返回
 * </ol>
 * <p>
 *所有这些例子都包含受限操作,因为对他们中的每一个,对所有线程而言,不一定能进行同时访问.
 *有时例子包含具体的资源(比如cpu或者锁),其他时候更为抽象(比如信号量的等待,条件变量或者join方法)
 *<p>
 * 所有线程方法调用时必须关中断(interrupts disabled)
 * <p>
 * Schedules access to some sort of resource with limited access constraints. A
 * thread queue can be used to share this limited access among multiple
 * threads.
 * <p>
 * </p>
 * <p>
 * Examples of limited access in Nachos include:

 * <ol>
 * <li>the right for a thread to use the processor. Only one thread may run on
 * the processor at a time.
 *
 * <li>the right for a thread to acquire a specific lock. A lock may be held by
 * only one thread at a time.
 *
 * <li>the right for a thread to return from <tt>Semaphore.P()</tt> when the
 * semaphore is 0. When another thread calls <tt>Semaphore.V()</tt>, only one
 * thread waiting in <tt>Semaphore.P()</tt> can be awakened.
 *
 * <li>the right for a thread to be woken while sleeping on a condition
 * variable. When another thread calls <tt>Condition.wake()</tt>, only one
 * thread sleeping on the condition variable can be awakened.
 *
 * <li>the right for a thread to return from <tt>KThread.join()</tt>. Threads
 * are not allowed to return from <tt>join()</tt> until the target thread has
 * finished.
 * </ol>
 * All these cases involve limited access because, for each of them, it is not
 * necessarily possible (or correct) for all the threads to have simultaneous
 * access. Some of these cases involve concrete resources (e.g. the processor,
 * or a lock); others are more abstract (e.g. waiting on semaphores, condition
 * variables, or join).
 *
 * <p>
 * All thread queue methods must be invoked with <b>interrupts disabled</b>.
 */
public abstract class ThreadQueue {
    /**
     * 当特定线程等待访问时,告知这个线程队列.如果线程不应被立即访问时,这个方法应该被调用.
     * (hg:简单说就是把某个等待资源线程加入该资源的等待队列时调用这个方法)
     * (举个栗子:如果线程想要得到一把锁但是另一个线程正持有这把锁时)
     * <p>
     * 一个线程不能同时等待访问多个资源.
     * 举个栗子:一个线程在等待一把锁时不能也等待获得cpu
     * 如果一个线程等待一把锁,他应该睡眠.
     * <p>
     *然而,由于对象的差异,当一个线程等待访问一个对象时,可能它正在访问另一个.
     *举个栗子:一个线程当持有一把锁时,可能会试图获取另一把.
     *注意,即便如此,当线程等待其他东西时,不能同时获得cpu.
     * <p>
     * Notify this thread queue that the specified thread is waiting for
     * access. This method should only be called if the thread cannot
     * immediately obtain access (e.g. if the thread wants to acquire a lock
     * but another thread already holds the lock).
     * <p>

     * A thread must not simultaneously wait for access to multiple resources.
     * For example, a thread waiting for a lock must not also be waiting to run
     * on the processor; if a thread is waiting for a lock it should be
     * sleeping.
     * <p>
     * However, depending on the specific objects, it may be acceptable for a
     * thread to wait for access to one object while having access to another.
     * For example, a thread may attempt to acquire a lock while holding
     * another lock. Note, though, that the processor cannot be held while
     * waiting for access to anything else.
     *
     * @param	thread	the thread waiting for access.
     */
    public abstract void waitForAccess(KThread thread);

    /**
     * 告知这个线程队列另一个线程可以接受访问.选择并且返回一个接受访问的线程,
     * 如果没有线程处于等待队列中,返回null
     * (hg:简单说就是从等待队列中获取一个线程，并且把获得的线程从队列中移除)
     * <p>
     * 如果限制访问的对象转让优先级,并且如果有其他对象等待访问,这会把优先级交给返回的那个
     * <p>
     * Notify this thread queue that another thread can receive access. Choose
     * and return the next thread to receive access, or <tt>null</tt> if there
     * are no threads waiting.
     * <p>

     * If the limited access object transfers priority, and if there are other
     * threads waiting for access, then they will donate priority to the
     * returned thread.
     *
     * @return	the next thread to receive access, or <tt>null</tt> if there
     *		are no threads waiting.
     */
    public abstract KThread nextThread();

    /**
    *告知这个线程队列一个线程正在接受访问,没有通过request()方法或者nextThread()方法;
     *举个栗子:如果一个线程获得了一把其他线程没有在等待的锁,这个线程应该调用这个方法
     * <p>
     * 这个方法不该被nextThread()返回的线程所调用
     * <p>
     * Notify this thread queue that a thread has received access, without
     * going through <tt>request()</tt> and <tt>nextThread()</tt>. For example,
     * if a thread acquires a lock that no other threads are waiting for, it
     * should call this method.
     * <p>
     * This method should not be called for a thread returned from
     * <tt>nextThread()</tt>.
     *
     * @param	thread	the thread that has received access, but was not
     * 			returned from <tt>nextThread()</tt>.
     */
    public abstract void acquire(KThread thread);

    /**
     * Print out all the threads waiting for access, in no particular order.
     * 不以特定顺序打印所有等待访问的线程.
     */
    public abstract void print();
}
